package cn.xzc.job.util;

import java.io.PrintWriter;
import java.io.StringWriter;

/**
 * 处理Throwable
 *
 * @author xzc
 * 当前时间 2024-02-12 21:30:00
 */
public class ThrowableUtil {
    /**
     * 将异常信息转换成字符串
     *
     * @param throwable 异常
     * @return 字符串
     */
    public static String getThrowableMessage(Throwable throwable) {
        StringWriter stringWriter = new StringWriter();
        String message;
        try (PrintWriter printWriter = new PrintWriter(stringWriter)) {
            throwable.printStackTrace(printWriter);
            message = stringWriter.toString();
        }
        return message;
    }

    /**
     * Build a message for the given base message and root cause.
     *
     * @param message the base message
     * @param cause   the root cause
     * @return the full exception message
     */
    
    public static String buildMessage(
                                      String message, 
                                      Throwable cause) {
        if (cause == null) {
            return message;
        }
        StringBuilder sb = new StringBuilder(64);
        if (message != null) {
            sb.append(message).append("; ");
        }
        sb.append(" exception info: ").append(getThrowableMessage(cause));
        return sb.toString();
    }

    /**
     * Retrieve the innermost cause of the given exception, if any.
     *
     * @param original the original exception to introspect
     * @return the innermost exception, or {@code null} if none
     */
    
    public static Throwable getRootCause(
                                         Throwable original) {
        if (original == null) {
            return null;
        }
        Throwable rootCause = null;
        Throwable cause = original.getCause();
        while (cause != null && cause != rootCause) {
            rootCause = cause;
            cause = cause.getCause();
        }
        return rootCause;
    }

    /**
     * Retrieve the most specific cause of the given exception, that is,
     * either the innermost cause (root cause) or the exception itself.
     * <p>Differs from {@link #getRootCause} in that it falls back
     * to the original exception if there is no root cause.
     *
     * @param original the original exception to introspect
     * @return the most specific cause (never {@code null})
     */
    public static Throwable getMostSpecificCause(Throwable original) {
        Throwable rootCause = getRootCause(original);
        return (rootCause != null ? rootCause : original);
    }

}
